package ch.holzi.paperracers.util;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;

public class Line
{
	private Vector p, v;
	private boolean isFinite;
	
	private static final String LOG_TAG = "Line";
	
	private static Paint paint = new Paint();
	{
		paint.setStyle(Paint.Style.STROKE);
		paint.setColor(Color.RED);
	}
	
	public Line(Vector p, Vector v)
	{
		this.p = new Vector(p);
		this.v = new Vector(v);
		isFinite = false;
	}
	
	public Line(Line s)
	{
		this.p = new Vector(s.p);
		this.v = new Vector(s.v);
		isFinite = s.isFinite;
	}
	
	public Line(Vector p, Vector v, boolean isFinite)
	{
		this.p = new Vector(p);
		this.v = new Vector(v);
		this.isFinite = isFinite;
	}
	
	public void setP(Vector v)
	{
		p.setX(v.getX());
		p.setY(v.getY());
	}
	
	public void setP(float x, float y)
	{
		p.setX(x);
		p.setY(y);
	}
	
	public void setV(Vector v)
	{
		this.v = v;
	}
	
	public void setV(float x, float y)
	{
		v.setX(x);
		v.setY(y);
	}

	public Vector getP()
	{
		return p;
	}
	
	public Vector getV()
	{
		return v;
	}
	
	public boolean isFinite()
	{
		return isFinite;
	}
	
	public Vector getPoint(float t)
	{
		return new Vector(p.getX() + t * v.getX(), p.getY() + t * v.getY());
	}
	
	public Vector getIntersection(Line l) throws Exception
	{
		float det = v.getX() * l.getV().getY() - v.getY() * l.getV().getX();
		
		if (det == 0)
		{
			float t = ( l.getP().getX() - p.getX() ) / v.getX();
			if ( (p.getY() + t * v.getY()) == l.getP().getY())
			{
				return new Vector(l.getP());
			}
			else
			{	
				Log.d(LOG_TAG, "lines are parallel and do not intersect");
				throw new Exception();
			}
		}
		
		float s = v.getX() * ( p.getX() - l.getP().getY() ) + v.getY() * ( l.getP().getX() - p.getX() ) / det;
		float t = ( l.getP().getX() - p.getX() ) / v.getX() + s * l.getV().getX() / v.getX();
		
		// both are infinite lines
		if (!isFinite && !l.isFinite())
		{
			 return getPoint(t);
		}
		// this one is finite, other one is infinite. need to check this one's parameter s_i
		else if (isFinite && !l.isFinite())
		{
			if (0 <= t && t <= 1)
			{
				return getPoint(t);
			}
			else
			{
				Log.d(LOG_TAG, "no intersection of finite and infinite line");
				throw new Exception();
			}
		}
		// this one is infinite, other is finite. need to check other one's parameter t_i
		else if (!isFinite && l.isFinite())
		{
			if (0 <= s && s <= 1)
			{
				return l.getPoint(s);
			}
			else
			{
				Log.d(LOG_TAG, "no intersection of infinite and finite line");
				throw new Exception();
			}
		}
		// both are finite. both parameters (s / t) have to be in range.
		else
		{
			if (0 <= t && t <= 1 && 0 <= s && s  <= 1)
			{
				return getPoint(s);
			}
			else
			{
				Log.d(LOG_TAG, "no intersection of finite lines");
				throw new Exception();
			}
		}
			
		
		
		/*
		// based on this = P0 + s * u and other = Q0 + t * v
		Vector w = p.substract(s.getP()); // P0 - Q0
		Vector v_orth = s.getV().orthogonal(true); // orthogonal vector of v of s
		
		float denom = v_orth.dot(v); // v_|_ * u
		
		// check if parallel
		if (denom == 0)
		{
			Log.d(LOG_TAG, "lines are parallel");
			throw new Exception();
		}
		
		v_orth.mult(-1);
		float s_i = v_orth.dot(w) / denom; // -v_|_ * w / v_|_ * u
		float t_i = v.orthogonal(true).dot(w) / -denom; // u_|_ * w / -v_|_ * u
		
		// both are inifinite lines
		if (!isFinite && !s.isFinite())
		{
			 return getPoint(s_i);
		}
		// this one is finite, other one is infinite. need to check this one's parameter s_i
		else if (isFinite && !s.isFinite())
		{
			if (0 <= s_i && s_i <= 1)
			{
				return getPoint(s_i);
			}
			else
			{
				Log.d(LOG_TAG, "no intersection of finite and infinite line");
				throw new Exception();
			}
		}
		// this one is infinite, other is finite. need to check other one's parameter t_i
		else if (!isFinite && isFinite())
		{
			if (0 <= t_i && t_i <= 1)
			{
				return s.getPoint(t_i);
			}
			else
			{
				Log.d(LOG_TAG, "no intersection of infinite and finite line");
				throw new Exception();
			}
		}
		// both are finite. both parameters (s_i / t_i) have to be in range.
		else
		{
			if (0 <= t_i && t_i <= 1 && 0 <= s_i && s_i <= 1)
			{
				return getPoint(s_i);
			}
			else
			{
				Log.d(LOG_TAG, "no intersection of finite lines");
				throw new Exception();
			}
		}*/
	}

	
	public String toString()
	{
		return "p= "+p+", v= "+v;
	}
}
